package cn.dzz.util;

import java.lang.reflect.Field;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author ArkD42
 * @file OA
 * @create 2020 - 06 - 17 - 23:04
 */
public class JdbcForTxUtil {

    // 有数据源和事务处理，那么这里不需要什么连接了
    private JdbcForTxUtil(){}

    /**
     * 连接对象交给了事务管理，这里只需要处理结果集资源和预编译对象即可
     * @param resultSet
     * @param preparedStatement
     */
    public static void closeResource(ResultSet resultSet, PreparedStatement preparedStatement){
        try {
            if (resultSet != null) resultSet.close();
            if (preparedStatement != null) preparedStatement.close();
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

    // 似乎后面只需要更改资源释放方法即可。。。

    public static PreparedStatement getPreparedStatement(Connection connection, String sql){
        try {
            return connection.prepareStatement(sql);
        } catch (SQLException sqlException) {
            sqlException.printStackTrace();
        }
        return null;
    }

    public static void argumentsInject(PreparedStatement preparedStatement,Object[] args){
        for (int i = 0; i < args.length; i++) {
            try {
                preparedStatement.setObject(i+1,args[i]);
            } catch (SQLException sqlException) {
                sqlException.printStackTrace();
            }
        }
    }

    public static int update(Connection connection,String sql,Object[] args) {
        PreparedStatement preparedStatement = getPreparedStatement(connection, sql);
        if (args != null) argumentsInject(preparedStatement,args);
        try { return preparedStatement.executeUpdate(); }
        catch (SQLException sqlException) { sqlException.printStackTrace(); }
        finally { closeResource(null,preparedStatement);}
        return 0;
    }

    public static <T> List<T> queryToList(Connection connection, Class<T> tClass, String sql, Object[] args){
        PreparedStatement preparedStatement = getPreparedStatement(connection, sql);
        if (args != null) argumentsInject(preparedStatement,args);
        ResultSet resultSet = null;
        try{
            resultSet = preparedStatement.executeQuery();
            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            List<T> tList = new ArrayList<T>();
            while(resultSet.next()){
                T t = tClass.newInstance();
                for (int i = 0; i < columnCount; i++) {
                    Object columnValue = resultSet.getObject(i + 1);
                    String columnLabel = metaData.getColumnLabel(i + 1);
                    Field field = tClass.getDeclaredField(columnLabel);
                    field.setAccessible( true );
                    field.set(t,columnValue);
                }
                tList.add(t);
            }
            return tList;
        } catch (Exception e){ e.printStackTrace(); }
        finally { closeResource(resultSet,preparedStatement);}
        return null;
    }

    public static List<Map<String, Object>> queryToList(Connection connection, String sql, Object[] args){
        PreparedStatement preparedStatement = getPreparedStatement(connection, sql);
        if (args != null) argumentsInject(preparedStatement,args);
        ResultSet resultSet = null;
        try{
            resultSet = preparedStatement.executeQuery();
            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            List<Map<String,Object>> mapList = new ArrayList<Map<String, Object>>();
            while(resultSet.next()){
                Map<String,Object> row = new HashMap<String, Object>();
                for (int i = 0; i < columnCount; i++) {
                    String columnLabel = metaData.getColumnLabel(i + 1);
                    Object columnValue = resultSet.getObject(i + 1);
                    row.put(columnLabel,columnValue);
                }
                mapList.add(row);
            }
            return mapList;
        }catch (Exception e){ e.printStackTrace(); }
        finally { closeResource(resultSet,preparedStatement);}
        return null;
    }

    public static <T> T queryOne(Connection connection,Class<T> tClass,String sql,Object[] args){
        PreparedStatement preparedStatement = getPreparedStatement(connection,sql);
        argumentsInject(preparedStatement,args);
        ResultSet resultSet = null;
        try{
            resultSet = preparedStatement.executeQuery();

            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            if (resultSet.next()){
                T t = tClass.newInstance();
                for (int i = 0; i < columnCount; i++) {
                    Object columnValue = resultSet.getObject(i + 1);
                    String columnLabel = metaData.getColumnLabel(i + 1);
                    Field field = tClass.getDeclaredField(columnLabel);
                    field.setAccessible( true );
                    field.set(t,columnValue);
                }
                return t;
            }
        }catch (Exception e){ e.printStackTrace();}
        finally { closeResource(resultSet,preparedStatement);}
        return null;
    }

    public static Map<String,Object> queryOne(Connection connection, String sql, Object[] args){
        PreparedStatement preparedStatement = getPreparedStatement(connection,sql);
        argumentsInject(preparedStatement,args);
        ResultSet resultSet = null;
        try{
            resultSet = preparedStatement.executeQuery();
            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            if (resultSet.next()){
                Map<String,Object> map = new HashMap<String, Object>();
                for (int i = 0; i < columnCount; i++) {
                    Object columnValue = resultSet.getObject(i + 1);
                    String columnLabel = metaData.getColumnLabel(i + 1);
                    map.put(columnLabel,columnValue);
                }
                return map;
            }
        }catch (Exception e){ e.printStackTrace();}
        finally { closeResource(resultSet,preparedStatement);}
        return null;
    }

    public static <E> E getValue(Connection connection,String sql,Object[] args){
        PreparedStatement preparedStatement = getPreparedStatement(connection, sql);
        if (args != null) argumentsInject(preparedStatement,args);
        ResultSet resultSet = null;
        try{
            resultSet = preparedStatement.executeQuery();
            if (resultSet.next())return (E)resultSet.getObject(1);;
        } catch (Exception e){ e.printStackTrace(); }
        finally{ closeResource(resultSet,preparedStatement);}
        return null;
    }

    public static java.sql.Date parseToSqlDate(String pattern, String patternTime){ //"yyyy-MM-dd"
        java.util.Date date = null;
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
            date = simpleDateFormat.parse(patternTime); //"1987-09-01"
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return new java.sql.Date(date.getTime());
    }



}
